﻿/*
 * @author Lee 
 * Time: 20180403 
 * Abstract: SharePoint API的二次封装
 */

using System;
using Microsoft.SharePoint;
using Microsoft.SharePoint.WebPartPages;
using Microsoft.SharePoint.Publishing;

namespace SharePointHelper.DLL.SSOM
{
	public class WebPart
	{
        /// <summary>
        /// web part scope
        /// </summary>
        public enum WebPartScope
        {
            Web,
            Site,
            WebApplication,
            Farm,
        }

        /// <summary>
        /// WebPart应插入的位置
        /// </summary>
        public enum WebPartLocation
        {
            Beginning,
            End,
            ReplaceKeyword,
            None,
        }
        /// <summary>
        /// 在rich content，将取代WebPart唯一的字符串
        /// </summary>
        public const string WebPartLocationReplacementKeyword = "^";

        /// <summary>
        /// 产生在一个特定的格式的一个新的web part id
        /// http://blog.mastykarz.nl/programmatically-adding-web-parts-rich-content-sharepoint-2010/
        /// </summary>
        /// <returns></returns>
        public static string CreateWebPartId(ref Guid guid)
        {
            guid = Guid.NewGuid();
            return String.Format("g_{0}", guid.ToString().Replace('-', '_'));
        }
        /// <summary>
        /// 产生在一个特定的格式的一个新的web part id
        /// http://blog.mastykarz.nl/programmatically-adding-web-parts-rich-content-sharepoint-2010/
        /// </summary>
        /// <returns></returns>
        public static string CreateWebPartId()
        {
            Guid guid = Guid.NewGuid();
            return CreateWebPartId(ref guid);
        }
        /// <summary>
        /// 创建一个web part Html来插入到一个rich content area中
        /// </summary>
        /// <param name="webPartId"></param>
        /// <returns></returns>
        public static string CreateWebPartHtml(Guid webPartId)
        {
            return string.Format("<div contenteditable='false' class='ms-rtestate-read ms-rte-wpbox'>"
                + "<div class='ms-rtestate-notify  ms-rtestate-read {0}' id='div_{0}' unselectable='on'></div>"
                + "<div unselectable='on' id='vid_{0}' style='display: none;'></div>"
                + "</div>", webPartId.ToString("D"));
        }

        #region 获取web parts manager/limited web parts manager
        /// <summary>
        /// 根据url获取 web parts manager 
        /// </summary>
        /// <param name="web"></param>
        /// <param name="pageUrl"></param>
        /// <returns></returns>
        public static SPLimitedWebPartManager GetWebPartManager(string pageUrl)
		{
			SPLimitedWebPartManager webPartManager = null;
			try
			{
				// 初始化
				if (pageUrl == null) { throw new Exception("PublishingPage passed is null"); }
				SPWeb web = Web.GetWeb();
				if (web == null) { throw new Exception("Failed to get SPWeb from passed url"); }
				if (!Validation.IsValidUrl(pageUrl)) { throw new Exception("Invalid page url passed"); }


				webPartManager = web.GetLimitedWebPartManager(pageUrl, System.Web.UI.WebControls.WebParts.PersonalizationScope.Shared);
			}
			catch (Exception ex)
			{
				Log.WriteError("srdgdfyjdGGtysrd", ex, "url: " + pageUrl);
				webPartManager = null;
			}
			return webPartManager;
		}

        /// <summary>
        /// 从 wiki 获取 publishing page的 SPFile对象中获取Web Part Manager
        /// </summary>
        /// <param name="file"></param>
        /// <returns></returns>
        public static SPLimitedWebPartManager GetWebPartManager(SPFile file)
		{
			SPLimitedWebPartManager webPartManager = null;
			try
			{
				// 初始化
				if (file == null) { throw new Exception("SPFile passed is null"); }
				webPartManager = file.GetLimitedWebPartManager(System.Web.UI.WebControls.WebParts.PersonalizationScope.Shared);
			}
			catch (Exception ex)
			{
				string pageUrl = null; if (file != null) { pageUrl = file.Url; }
				Log.WriteError("trydtrgfdfsdrtrdts", ex, "url: " + pageUrl);
				webPartManager = null;
			}
			return webPartManager;
		}

        /// <summary>
        /// 根据 publishing page 获取 web part manager 
        /// </summary>
        /// <param name="page"></param>
        /// <returns></returns>
        public static SPLimitedWebPartManager GetWebPartManager(PublishingPage page)
		{
			SPLimitedWebPartManager webPartManager = null;
			try
			{
				// 初始化
				if (page == null) { throw new Exception("PublishingPage passed is null"); }

				webPartManager = GetWebPartManager(page.ListItem.File);
			}
			catch (Exception ex)
			{
				string pageUrl = null; if (page != null) { pageUrl = page.Url; }
				Log.WriteError("srdgdfyjdGGtysrd", ex, "url: " + pageUrl);
				webPartManager = null;
			}
			return webPartManager;
		}

        /// <summary>
        /// 获取webPart page的LimitedWebPartManager，比如 wiki page
        /// </summary>
        /// <param name="item"></param>
        /// <returns></returns>
        public static SPLimitedWebPartManager GetWebPartManager(SPListItem item)
		{
			SPLimitedWebPartManager webPartManager = null;
			try
			{
				// 初始化
				if (item == null) { throw new Exception("SPListItem passed is null"); }
				if (item.File == null) { throw new Exception("item.File is null"); }

				webPartManager = GetWebPartManager(item.File);
			}
			catch (Exception ex)
			{
				string itemUrl = null; if (item != null) { itemUrl = item.Url; }
				Log.WriteError("strydjrdthrsersetrrs", ex, "url: " + itemUrl);
				webPartManager = null;
			}
			return webPartManager;
		}
        #endregion

        #region 获取web part的url
        /// <summary>
        /// 获取web part的url
        /// 这是一个Web part的链接，用于添加到页面
        /// </summary>
        /// <param name="web"></param>
        /// <param name="webPartFilename"></param>
        /// <param name="scope"></param>
        /// <returns></returns>
        public static string GetWebPartUrl(SPWeb web, string webPartFilename, WebPartScope scope)
		{
			string url = null;
			try
			{
				// 初始化
				if (web == null) { web = Web.GetWeb(); }
				if (web == null) { throw new Exception("SPWeb passed is null and failed to get it from SPContext"); }
				if (string.IsNullOrEmpty(webPartFilename)) { throw new Exception("WebPart filename passed is null"); }


				if (scope == WebPartScope.Web)
				{
					url = web.Url + "/_catalogs/wp/" + webPartFilename;
				}
				else if (scope == WebPartScope.Site)
				{
					url = web.Site.RootWeb.Url + "/_catalogs/wp/" + webPartFilename;
				}
				else
				{
					throw new Exception("Don't know how to get url for webpart in scope: " + scope.ToString());
				}
			}
			catch (Exception ex)
			{
				Log.WriteError("sdtfguidstrsrdsdr", ex);
			}
			return url;
		}
        #endregion

        #region 获取web part
        /// <summary>
        /// 获取web part
        /// </summary>
        /// <param name="web"></param>
        /// <param name="pageUrl"></param>
        /// <param name="webPartUrl"></param>
        /// <returns></returns>
        public static System.Web.UI.WebControls.WebParts.WebPart GetWebPart(SPLimitedWebPartManager webPartManager, 
			string webPartFilename, WebPartScope scope)
		{
			System.Web.UI.WebControls.WebParts.WebPart webpart = null;
			try
			{
				// 初始化
				if (webPartManager == null) { throw new Exception("webPartManager passed is null"); }
				if (string.IsNullOrEmpty(webPartFilename)) { throw new Exception("Web Part Filename passed is null"); }


				// 获取 web part的Url
				string webPartUrl = GetWebPartUrl(webPartManager.Web, webPartFilename, scope);
				if (string.IsNullOrEmpty(webPartUrl)) { throw new Exception("Failed to get webPart url using filename: " + webPartFilename + " and scope: " + scope); }

                // 获取 web part的xml reader  
                System.Xml.XmlTextReader reader = new System.Xml.XmlTextReader(
				    new System.IO.StringReader(webPartManager.Web.GetFileAsString(webPartUrl)));
				if (reader == null || reader.IsEmptyElement) { throw new Exception("Failed to get webpart using url: " + webPartUrl); }

				// 获取 webpart 对象
				string errorMessage = null;
				webpart = webPartManager.ImportWebPart(reader, out errorMessage);
				if (webpart == null || !string.IsNullOrEmpty(errorMessage))
				{
				    throw new Exception("Failed to reference webpart using url: " + webPartUrl + " with error: "
				    + errorMessage);
				}
			}
			catch (Exception ex)
			{
				Log.WriteError("7iurewtJJrtyfddsfsdhf", ex, "webPart filename: " + webPartFilename);
				webpart = null;
			}
			return webpart;
		}
        #endregion

        #region 根据web part Id(string类型)获取Id的GUID类型
        /// <summary>
        /// 根据web part Id(string类型)获取Id的GUID类型
        /// </summary>
        /// <param name="webPartId"></param>
        /// <returns></returns>
        public static Guid GetGuidFromWebPartId(string webPartId)
		{
			string originalWebPartId = webPartId;
			Guid guid = Guid.Empty;
			if (!string.IsNullOrEmpty(webPartId))
			{
                // “g_”前缀
                if (webPartId.Length > 2 && webPartId.Substring(0, 2) == "g_")
				{
					webPartId = webPartId.Substring(2);
				}

                // 用破折号替换下划线
                webPartId = webPartId.Replace("_", "-").Trim();

                // 尝试转换为GUID
                try { guid = new Guid(webPartId); }
				catch (Exception ex)
				{
					Log.WriteError("erge67erhed", ex, "original webpartId: " + originalWebPartId
						+ " formatted id: " + webPartId);
				}
			}
			return guid;
		}
        #endregion

        #region 添加一个新的 web part
        /// <summary>
        /// 添加一个新的 web part
        /// IMPORTANT: 需要保存WebPart所添加进的item或publishinpage
        /// http://blog.mastykarz.nl/programmatically-adding-web-parts-rich-content-sharepoint-2010/
        /// </summary>
        /// <param name="page"></param>
        /// <param name="webPartUrl"></param>
        public static string AddWebPart(SPFile file, string webPartFilename,  int? zoneIndex, bool isTurnOffChrome)
		{
			string webPartHtml = null;
			try
			{
				// 初始化
				if (file == null) { throw new Exception("SPFile passed is null"); }
				if (string.IsNullOrEmpty(webPartFilename)) { throw new Exception("WebPart filename passed is null"); }


				// 获取 webPartManager
				using (SPLimitedWebPartManager webPartManager = GetWebPartManager(file))
				{
					// 获取 webPart
					System.Web.UI.WebControls.WebParts.WebPart webPartToAdd = GetWebPart(webPartManager, webPartFilename, WebPartScope.Site);
					if (webPartToAdd == null) { throw new Exception("Failed to get webpart using filename: " + webPartFilename); }

                    // 将Web part添加到隐藏的Web part区域
                    if (zoneIndex == null) { zoneIndex = 0; }
					Guid guid = Guid.Empty;
					webPartToAdd.ID = CreateWebPartId(ref guid);
					if (isTurnOffChrome) { webPartToAdd.ChromeType = System.Web.UI.WebControls.WebParts.PartChromeType.None; }
					webPartManager.AddWebPart(webPartToAdd, "wpz", (int)zoneIndex);

                    // 创建Web part html添加到页面的Rich Content
                    webPartHtml = CreateWebPartHtml(guid);
				}
			}
			catch (Exception ex)
			{
				Log.WriteError("dxfyggcdfdtyrdrxxcxcfdxr54", ex, "webpartFilename: " + webPartFilename);
				webPartHtml = null;
			}
			return webPartHtml;
		}
        #endregion

        #region 在wiki page/publishing page中添加一个已经存在的list的XsltListViewWebPart
        /// <summary>
        /// 在wiki page/publishing page中添加一个已经存在的list的XsltListViewWebPart
        /// </summary>
        /// <param name="file"></param>
        /// <param name="listName"></param>
        /// <param name="zoneIndex"></param>
        /// <param name="isTurnOffChrome"></param>
        /// <returns></returns>
        public static string AddListWebPart(SPFile file, string listName, int? zoneIndex, bool isTurnOffChrome)
		{
			string webPartHtml = null;
			try
			{
				// 初始化
				if (file == null) { throw new Exception("SPFile passed is null"); }
				if (string.IsNullOrEmpty(listName)) { throw new Exception("list name passed is null"); }


				// 获取 webPartManager
				using (SPLimitedWebPartManager webPartManager = GetWebPartManager(file))
				{
					// 获取 list webpart
					XsltListViewWebPart listWebPart = new XsltListViewWebPart();
					listWebPart.ListDisplayName = listName;
					if (isTurnOffChrome) { listWebPart.ChromeType = System.Web.UI.WebControls.WebParts.PartChromeType.None; }

					// add webpart to the hidden webparts zone
					if (zoneIndex == null) { zoneIndex = 0; }
					Guid guid = Guid.Empty;
					listWebPart.ID = CreateWebPartId(ref guid);
					webPartManager.AddWebPart(listWebPart, "wpz", (int)zoneIndex);

                    // 创建Web part html添加到页面的Rich Content
                    webPartHtml = CreateWebPartHtml(guid);
				}
			}
			catch (Exception ex)
			{
				Log.WriteError("tr67ufhgkljdsghioesriudk", ex, "listName: " + listName);
				webPartHtml = null;
			}
			return webPartHtml;
		}
        #endregion

        #region 添加一个web part到Publishing Page中
        /// <summary>
        /// 添加一个web part到Publishing Page中
        /// </summary>
        /// <param name="page"></param>
        /// <param name="webPartFilename"></param>
        /// <param name="zoneIndex"></param>
        /// <param name="webPartLocation"></param>
        /// <param name="isTurnOffChrome"></param>
        /// <param name="isSave"></param>
        /// <returns></returns>
        public static bool AddWebPart(PublishingPage page, string webPartFilename, int? zoneIndex,
			WebPartLocation webPartLocation, bool isTurnOffChrome, bool isSave)
		{
			bool isSuccess = false;
			try
			{
				// 初始化
				if (page == null) { throw new Exception("PublishinPage passed is null"); }


				// 获取 WebPartManager
				SPLimitedWebPartManager webPartManager = GetWebPartManager(page);

				string webPartHtml = AddWebPart(page.ListItem.File, webPartFilename, zoneIndex, isTurnOffChrome);
				if (string.IsNullOrEmpty(webPartHtml)) { throw new Exception("Failed to add WebPart to page: " + page.Url); }

				// 插入 webPart html 引用
				if (webPartLocation == WebPartLocation.Beginning)
				{
					page.ListItem["PublishingPageContent"] = webPartHtml + page.ListItem["PublishingPageContent"];
				}
				else if (webPartLocation == WebPartLocation.End)
				{
					page.ListItem["PublishingPageContent"] = page.ListItem["PublishingPageContent"] + webPartHtml;
				}
				else if (webPartLocation == WebPartLocation.ReplaceKeyword)
				{
					string keyword = WebPartLocationReplacementKeyword;
					if (!string.IsNullOrEmpty(keyword))
					{
						page.ListItem["PublishingPageContent"] = ((string)page.ListItem["PublishingPageContent"]).Replace(keyword, webPartHtml);
					}
				}
				else if (webPartLocation == WebPartLocation.None)
				{
                    // 什么也不做，成员将返回你手动添加到发布页面的Web part的HTML。
                }
                else
				{
					throw new Exception("Unknown webpart location option: " + webPartLocation.ToString());
				}

				isSuccess = true;
			}
			catch (Exception ex)
			{
				string pageUrl = null; if (page != null) { pageUrl = page.Url; }
				Log.WriteError("se5y4eu8dstretduyyuyg", ex, "pageUrl: " + pageUrl);
				isSuccess = false;
			}
			return isSuccess;
		}
        #endregion

        #region 移除某个页面的所有 webParts
        /// <summary>
        /// 移除某个页面的所有 web Parts : PublishingPage or wiki page
        /// </summary>
        /// <param name="file"></param>
        public static void ClearAll(SPFile file)
		{
			try
			{
				// 初始化
				if (file == null) { throw new Exception("SPFile passed is null"); }
				SPLimitedWebPartManager webPartManager = GetWebPartManager(file);
				if (webPartManager == null) { throw new Exception("Failed to get webPartManger"); }

				while (webPartManager.WebParts.Count > 0)
				{
					webPartManager.DeleteWebPart(webPartManager.WebParts[0]);
				}
			}
			catch (Exception ex)
			{
				string pageUrl = null; if (file != null) { pageUrl = file.Url; }
				Log.WriteError("rtsydetrjther457rt", ex, "url:" + pageUrl);
			}
		}
        #endregion


    }
}
